#ifndef __BUFFER_HPP__
#define __BUFFER_HPP__

#include "common.hpp"
#include "debug.h"

//---------------------------------------
// Stream format buffer support moduel
//---------------------------------------

class Buffer ;
class BufferNode;

class BufferNode 
{
  friend class Buffer;

public:

  BufferNode () : 
    next (this), prev (this), ptr (NULL), len (0), seq (0)
  { debug (DEBUG_CREATE, "this = %p", this); } 

  BufferNode (byte_t * p, unsigned int size) : 
    next (this), prev (this), ptr (NULL), len (0), seq (0)
  { debug (DEBUG_CREATE, "this = %p", this); setData (p, size); } 

  BufferNode (byte_t * p, unsigned int size, u_int32_t seq): 
    next (this), prev (this), ptr (NULL), len (0), seq (0)
  { debug (DEBUG_CREATE, "this = %p", this); setData (p, size, seq); }

  ~BufferNode ()
  {
    if (ptr)
      delete ptr;
  }

  void setData (byte_t * p, unsigned int size);
  void setData (byte_t * p, unsigned int size, u_int32_t seq);

private:
  static const int DEBUG_CREATE = false;
  BufferNode * next, * prev;
  byte_t * ptr;
  unsigned int len;
  u_int32_t seq;
};


class Buffer 
{
public:
  Buffer () : mode (BM_NULL) {};
  ~Buffer () {};

  bool write (byte_t * ptr, unsigned int len);
  bool write (byte_t * ptr, unsigned int len, u_int32_t seq);
  byte_t * fetch (unsigned int * len);
  byte_t * fetch (unsigned int * len, unsigned int reqLen);

private:
  static const int DEBUG_LINK   = false;

  void attach (BufferNode * prev, BufferNode * node);
  void detach (BufferNode * node);
  unsigned int getValidSize ();

  BufferNode root;

  enum BufferMode
    {
      BM_NULL = 0,
      BM_BLOCK,
      BM_STREAM
    } mode;
};


#endif /* __BUFFER_HPP__ */
